package de.mnit.schnipsel.db;

import de.mnit.basis.daten.BenutzerEingabe;
import de.mnit.basis.daten.FormatText;
import de.mnit.basis.daten.struktur.S_Folge;
import de.mnit.basis.daten.struktur.container.DBKiste;
import de.mnit.basis.daten.struktur.liste.S_Liste;
import de.mnit.basis.daten.struktur.tabelle.S_Tabelle;
import de.mnit.basis.daten.struktur.tabelle.typ.TypTabelle2;
import de.mnit.basis.db.konstant.DBMS;
import de.mnit.basis.db.sql.SqlHilfe;
import de.mnit.basis.db.sys3e.e1_basis.A_E1_H;
import de.mnit.basis.fehler.Fehler;
import de.mnit.basis.fehler.benutzer.F_Benutzer;
import de.mnit.basis.sys.Ausgabe;

/**
 * @author Michael Nitsche
 */
public class DBZ_Baum extends A_E1_H<DBManager> implements S_DBZ_Baum {

	private final B_Baum k=B_Baum.info;


	public DBZ_Baum(DBManager manager) {
		super(manager, "baum");
//		db().befehl("ALTER TABLE "+tab+" DROP COLUMN art");
//		db().befehl("ALTER TABLE "+tab+" ADD COLUMN "+B_Baum.info.OFFEN.gName()+" BOOLEAN DEFAULT TRUE NOT NULL");

//		db().befehl("ALTER TABLE "+tab+" ADD COLUMN "+B_Baum.info.SORTIERUNG.gName()+" INTEGER DEFAULT 0 NOT NULL");
//		db().befehl("ALTER TABLE "+tab+" ADD COLUMN "+B_Baum.info.GESCHUETZT.gName()+" BOOLEAN DEFAULT false NOT NULL");
	}


	/**
	 * id,Oben,Titel,Offen,Geschützt,KinderAnzahl
	 */
	public S_Tabelle<String> gTabBaum() {
		String sqlKinder="(SELECT COUNT("+k.ID.gName()+")>0 FROM "+tab+" b WHERE a."+k.ID.gName()+"="+k.OBEN.gName()+")";
		String sql="SELECT "+k.ID.gName()+","+k.OBEN.gName()+","+k.TITEL.gName()+",'',"+iSqlBool(k.OFFEN)+","+iSqlBool(k.GESCHUETZT)+","+iSqlBool(sqlKinder)+" FROM "+tab+" a ORDER BY sortierung";
		return this.db().gib(sql);
	}

	//TODO: Achtung 1 vs. True
	public S_Tabelle<String> gTabExport() {
		String spalten=SqlHilfe.zuSQLSpalten(k.ID, k.OBEN, k.TITEL, iSqlBool(k.GESCHUETZT), iSqlBool(k.OFFEN), k.SORTIERUNG);
		String sql="SELECT "+spalten+" FROM "+tab;
		return this.db().gib(sql);
	}

//	public S_Tabelle<String> gTabExport(int root) {
//		String sql="SELECT "+k.ID.gName()+","+k.OBEN.gName()+","+k.TITEL.gName()+" FROM "+tab;
//		return this.db().gib(sql);
//	}

	public TypTabelle2<Integer,Boolean> gTabOffen() {
		String sql="SELECT "+k.ID.gName()+","+iZuBool(k.OFFEN.gName())+" FROM "+tab;
		S_Tabelle<String> dberg=this.db().gib(sql);
		TypTabelle2<Integer,Boolean> erg=TypTabelle2.neu(Integer.class,Boolean.class);
		for(S_Folge<String> z : dberg)
			erg.plus(Integer.parseInt(z.gib(1)), Boolean.parseBoolean(z.gib(2)));
		return erg;
	}

	public boolean existiert(int id) {
		String sql="SELECT COUNT("+k.ID.gName()+") FROM "+tab+" WHERE id="+id;
		return db().gibInt(sql)>0;
	}

	public boolean gGeschuetzt(int id) {
		if(id<0) return false;
		String sql="SELECT "+iSqlBool(k.GESCHUETZT)+" FROM "+tab+" WHERE id="+id;
		return db().gibBool(sql);
	}

	public Integer gVater(int id) {
		String sql="SELECT "+k.OBEN.gName()+" FROM "+tab+" WHERE id="+id;
		return db().gibWInteger(sql);
	}

	public Integer plus(Integer vater, String titel) {
		String titel2=FormatText.zuDB_Text(titel);
		String sql1="INSERT INTO "+tab+" (oben,titel,sortierung) VALUES ("+vater+","+titel2+",9999999)";
		String sql2="SELECT "+SqlHilfe.letzteID(m().gDBMS())+" FROM "+tab;
		this.db().befehl(sql1);
		int id= this.db().gibInt(sql2);
		Ausgabe.debug(id);

		sSortierung(id, vater, Integer.MAX_VALUE);
		return id;
	}

	public void minus(int id) {
		b("DELETE FROM "+tab+" WHERE id="+id);
		b("UPDATE schnipsel SET ast=null WHERE ast="+id); //SCHNIPSEL
	}

	/**
	 * index= 0 bis
	 */
	public void verschieben(int id, Integer neuerVater, Integer index) {
		String sql="UPDATE "+tab+" SET oben="+neuerVater+" WHERE id="+id;
		this.db().befehl(sql);
		sSortierung(id, neuerVater, index);
	}

	public void sSortierung(int id, Integer neuerVater, Integer index) { //TODO HISTORY plus!!!
		String oben= neuerVater==null ? " IS NULL" : "="+neuerVater;

		if(index==null) {
			Ausgabe.warnung(id, neuerVater, index);
			return;
		}

		String sql="SELECT id FROM "+tab+" WHERE oben"+oben+" ORDER BY sortierung"; //+" AND id!="+id
		S_Liste<String> sort= db().gibSpalte(sql);
		if(index>sort.gLaenge())
			index=sort.gLaenge();

		sort.plus(index+1, id+"");
		for(int pos=1; pos<=sort.gLaenge(); pos++) {
			sql="UPDATE "+tab+" SET sortierung="+pos+" WHERE id="+sort.gib(pos);
			this.db().befehl(sql);
		}
		sql="UPDATE "+tab+" SET sortierung="+(index+1)+" WHERE id="+id;
		this.db().befehl(sql);
	}

	public void leeren() {
		b("DELETE FROM "+tab);
		b("UPDATE schnipsel SET ast=null"); //SCHNIPSEL
	}

	public void importiere(String id, String oben, String titel, String geschuetzt, String offen, String sort) throws F_Benutzer {
		int iid=BenutzerEingabe.zuInt(id);
		String felder=SqlHilfe.zuSQLSpalten(k.ID, k.OBEN, k.TITEL, k.GESCHUETZT, k.OFFEN, k.SORTIERUNG);
		String sql="INSERT INTO "+tab+" ("+felder+") VALUES ("
			+iid+","
			+BenutzerEingabe.zuWInt(oben)+","
			+BenutzerEingabe.zuStringDB(titel)+","
//			+Typ.zuInt(art)+","
			+BenutzerEingabe.zuBool(geschuetzt)+","
			+BenutzerEingabe.zuBool(offen)+","
			+BenutzerEingabe.zuInt(sort)+")";
		this.db().befehl(sql);
	}

	public void sStatus(int id, boolean offen) {
		String sql="UPDATE "+tab+" SET offen="+offen+" WHERE id="+id;
		this.db().befehl(sql);
	}

	public void sGeschuetzt(int id, boolean geschuetzt) {
		String sql="UPDATE "+tab+" SET geschuetzt="+geschuetzt+" WHERE id="+id;
		this.db().befehl(sql);
	}

	public void umbenennen(int id, String neu) {
		String neu2=FormatText.zuDB_Text(neu);
		String sql="UPDATE "+tab+" SET titel="+neu2+" WHERE id="+id;
		this.db().befehl(sql);
	}

	// INTERN

	protected void erstellen() {
		DBMS dbms=this.m().gDBMS();
		if(dbms==DBMS.HSQLDB) {
//			NeuTab_HSqlDB tab=new NeuTab_HSqlDB(this.m().direkt(), this.tab);
//			tab.spaltenErstellen(B_Baum.info);
			this.b("CREATE TABLE baum(" +
				"id INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) NOT NULL PRIMARY KEY," +
				"oben INTEGER," +
				"titel VARCHAR(256) NOT NULL," +
				"art INTEGER NOT NULL,BILD VARCHAR(256)," +
				"offen BOOLEAN DEFAULT TRUE NOT NULL)");
			this.b("CREATE INDEX i_sortierung ON baum (sortierung)");
		}
		else if(dbms==DBMS.MYSQL) {
			this.b("CREATE TABLE baum(" +
				"id INTEGER NOT NULL AUTO_INCREMENT," +
				"oben INTEGER," +
				"titel VARCHAR(256) NOT NULL," +
//				"art INTEGER NOT NULL," +
				"geschuetzt BOOLEAN DEFAULT FALSE NOT NULL," +
				"offen BOOLEAN DEFAULT TRUE NOT NULL," +
				"sortierung INTEGER NOT NULL," +
				"PRIMARY KEY(id))");
			this.b("CREATE INDEX i_sortierung ON baum (sortierung)");
		}
		else Fehler.sonstige.da_ToDo(dbms);
//		this.b("ALTER TABLE "+this.tab+" ALTER COLUMN "+B_Baum.info.ID.gName()+" RESTART WITH 100;");
	}

	private boolean iZuBool(String s) {
		return m().gDBMS() == DBMS.HSQLDB ? Boolean.parseBoolean(s)
			: s.equals("1");
	}

	public String iSqlBool(DBKiste<Boolean> kb) {
		return iSqlBool(kb.gName());
	}

	public String iSqlBool(String s) {
		return this.m().gDBMS()==DBMS.HSQLDB ? s : "IF("+s+"=1,'true','false')";
	}

}
